using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;

namespace HalconDotNet
{
	public class HSerializedItem : HHandle
	{
		[EditorBrowsable(EditorBrowsableState.Never)]
		public HSerializedItem()
			: base(HHandleBase.UNDEF)
		{
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public HSerializedItem(IntPtr handle)
			: base(handle)
		{
			AssertSemType();
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public HSerializedItem(HHandle handle)
			: base(handle)
		{
			AssertSemType();
		}

		private void AssertSemType()
		{
			AssertSemType("serialized_item");
		}

		internal static int LoadNew(IntPtr proc, int parIndex, int err, out HSerializedItem obj)
		{
			obj = new HSerializedItem(HHandleBase.UNDEF);
			return obj.Load(proc, parIndex, err);
		}

		internal static int LoadNew(IntPtr proc, int parIndex, int err, out HSerializedItem[] obj)
		{
			err = HTuple.LoadNew(proc, parIndex, err, out HTuple tuple);
			obj = new HSerializedItem[tuple.Length];
			for (int i = 0; i < tuple.Length; i++)
			{
				obj[i] = new HSerializedItem(HalconAPI.IsLegacyHandleMode() ? tuple[i].IP : ((IntPtr)tuple[i].H));
			}
			tuple.Dispose();
			return err;
		}

		public HSerializedItem(IntPtr pointer, int size, string copy)
		{
			IntPtr proc = HalconAPI.PreCall(410);
			HalconAPI.StoreIP(proc, 0, pointer);
			HalconAPI.StoreI(proc, 1, size);
			HalconAPI.StoreS(proc, 2, copy);
			HalconAPI.InitOCT(proc, 0);
			int err = HalconAPI.CallProcedure(proc);
			err = Load(proc, 0, err);
			HalconAPI.PostCall(proc, err);
			GC.KeepAlive(this);
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public HSerializedItem(byte[] data)
		{
			GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
			IntPtr pointer = gCHandle.AddrOfPinnedObject();
			CreateSerializedItemPtr(pointer, data.Length, "true");
			gCHandle.Free();
		}

		public static implicit operator byte[](HSerializedItem item)
		{
			int size;
			IntPtr serializedItemPtr = item.GetSerializedItemPtr(out size);
			byte[] array = new byte[size];
			Marshal.Copy(serializedItemPtr, array, 0, size);
			GC.KeepAlive(item);
			return array;
		}

		internal new void Serialize(Stream stream)
		{
			byte[] array = this;
			stream.Write(array, 0, array.Length);
		}

		internal new static HSerializedItem Deserialize(Stream stream)
		{
			BinaryReader binaryReader = new BinaryReader(stream);
			byte[] array = binaryReader.ReadBytes(16);
			if (array.Length < 16 || HalconAPI.IsFailure(HalconAPI.GetSerializedSize(array, out ulong size)))
			{
				throw new HalconException("Input stream is no serialized HALCON object");
			}
			if (size > 2415918079u)
			{
				throw new HalconException("Input stream too large");
			}
			byte[] array2 = binaryReader.ReadBytes((int)size);
			if (array2.Length < (int)size || HalconAPI.IsFailure(HalconAPI.GetSerializedSize(array, out size)))
			{
				throw new HalconException("Unexpected end of serialization data");
			}
			int num = (int)size + 16;
			byte[] array3 = new byte[num];
			array.CopyTo(array3, 0);
			array2.CopyTo(array3, 16);
			return new HSerializedItem(array3);
		}

		public void ReceiveSerializedItem(HSocket socket)
		{
			Dispose();
			IntPtr proc = HalconAPI.PreCall(403);
			HalconAPI.Store(proc, 0, socket);
			HalconAPI.InitOCT(proc, 0);
			int err = HalconAPI.CallProcedure(proc);
			err = Load(proc, 0, err);
			HalconAPI.PostCall(proc, err);
			GC.KeepAlive(this);
			GC.KeepAlive(socket);
		}

		public void SendSerializedItem(HSocket socket)
		{
			IntPtr proc = HalconAPI.PreCall(404);
			Store(proc, 1);
			HalconAPI.Store(proc, 0, socket);
			int procResult = HalconAPI.CallProcedure(proc);
			HalconAPI.PostCall(proc, procResult);
			GC.KeepAlive(this);
			GC.KeepAlive(socket);
		}

		public void FwriteSerializedItem(HFile fileHandle)
		{
			IntPtr proc = HalconAPI.PreCall(405);
			Store(proc, 1);
			HalconAPI.Store(proc, 0, fileHandle);
			int procResult = HalconAPI.CallProcedure(proc);
			HalconAPI.PostCall(proc, procResult);
			GC.KeepAlive(this);
			GC.KeepAlive(fileHandle);
		}

		public void FreadSerializedItem(HFile fileHandle)
		{
			Dispose();
			IntPtr proc = HalconAPI.PreCall(406);
			HalconAPI.Store(proc, 0, fileHandle);
			HalconAPI.InitOCT(proc, 0);
			int err = HalconAPI.CallProcedure(proc);
			err = Load(proc, 0, err);
			HalconAPI.PostCall(proc, err);
			GC.KeepAlive(this);
			GC.KeepAlive(fileHandle);
		}

		public static void ClearSerializedItem(HSerializedItem[] serializedItemHandle)
		{
			HTuple hTuple = HHandleBase.ConcatArray(serializedItemHandle);
			IntPtr proc = HalconAPI.PreCall(408);
			HalconAPI.Store(proc, 0, hTuple);
			int procResult = HalconAPI.CallProcedure(proc);
			HalconAPI.UnpinTuple(hTuple);
			HalconAPI.PostCall(proc, procResult);
			GC.KeepAlive(serializedItemHandle);
		}

		public void ClearSerializedItem()
		{
			IntPtr proc = HalconAPI.PreCall(408);
			Store(proc, 0);
			int procResult = HalconAPI.CallProcedure(proc);
			HalconAPI.PostCall(proc, procResult);
			GC.KeepAlive(this);
		}

		public IntPtr GetSerializedItemPtr(out int size)
		{
			IntPtr proc = HalconAPI.PreCall(409);
			Store(proc, 0);
			HalconAPI.InitOCT(proc, 0);
			HalconAPI.InitOCT(proc, 1);
			int err = HalconAPI.CallProcedure(proc);
			err = HalconAPI.LoadIP(proc, 0, err, out IntPtr intPtrValue);
			err = HalconAPI.LoadI(proc, 1, err, out size);
			HalconAPI.PostCall(proc, err);
			GC.KeepAlive(this);
			return intPtrValue;
		}

		public void CreateSerializedItemPtr(IntPtr pointer, int size, string copy)
		{
			Dispose();
			IntPtr proc = HalconAPI.PreCall(410);
			HalconAPI.StoreIP(proc, 0, pointer);
			HalconAPI.StoreI(proc, 1, size);
			HalconAPI.StoreS(proc, 2, copy);
			HalconAPI.InitOCT(proc, 0);
			int err = HalconAPI.CallProcedure(proc);
			err = Load(proc, 0, err);
			HalconAPI.PostCall(proc, err);
			GC.KeepAlive(this);
		}
	}
}
